import cv2
import numpy as np
from datetime import datetime
from cap import VideoCapture
import time

class CardEdgeDetector:
    """卡片边缘检测模块（针对白色背景，褐色边缘）"""
    
    def __init__(self):
        # 检测参数
        self.min_contour_area = 1000  # 最小轮廓面积，过滤小噪声
        self.epsilon_factor = 0.03  # 轮廓近似精度因子
        self.canny_low = 30  # Canny 边缘检测低阈值
        self.canny_high = 100  # Canny 边缘检测高阈值
        
    def detect_card_edge(self, img):
        """检测卡片的褐色边缘"""
        try:
            # 转换为 HSV 颜色空间，分割褐色边缘
            hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
            # 褐色 HSV 范围（大致为橙棕色，需根据实际调整）
            lower_brown = np.array([10, 50, 50])  # 色调 10-30，饱和度 50-255，亮度 50-255
            upper_brown = np.array([30, 255, 255])
            mask = cv2.inRange(hsv, lower_brown, upper_brown)
            
            # 形态学操作：闭运算连接边缘，填充小孔
            kernel = np.ones((7, 7), np.uint8)
            mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations=2)
            # 开运算去除小噪声
            mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=1)
            
            # 高斯模糊去噪
            blurred = cv2.GaussianBlur(mask, (5, 5), 0)
            # 边缘检测
            edges = cv2.Canny(blurred, self.canny_low, self.canny_high)
            
            # 查找轮廓
            contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
            
            # 保存最大轮廓（假设卡片轮廓面积最大）
            max_contour = None
            max_area = 0
            for contour in contours:
                area = cv2.contourArea(contour)
                print(f"检测到轮廓: 面积={area}")
                if area < self.min_contour_area:
                    continue
                
                # 近似轮廓为多边形
                epsilon = self.epsilon_factor * cv2.arcLength(contour, True)
                approx = cv2.approxPolyDP(contour, epsilon, True)
                
                # 判断是否为四边形
                if len(approx) == 4:
                    if area > max_area:
                        max_area = area
                        max_contour = approx
                        x, y, w, h = cv2.boundingRect(approx)
                        print(f"检测到四边形: 位置=({x}, {y}), 宽={w}, 高={h}, 面积={area}")
            
            if max_contour is not None:
                print("检测到卡片边缘（褐色）")
                self._visualize(img, max_contour, mask, edges, True)
                return True, {
                    'status': 'edge_detected',
                    'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                    'bbox': cv2.boundingRect(max_contour)
                }
            
            print("未检测到卡片边缘")
            self._visualize(img, None, mask, edges, False)
            return False, {
                'status': 'no_edge',
                'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'bbox': None
            }
        
        except Exception as e:
            print(f"边缘检测失败: {str(e)}")
            return False, {
                'status': 'error',
                'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'error': str(e)
            }

    def _visualize(self, img, contour, mask, edges, detected):
        """可视化检测结果"""
        debug_img = img.copy()
        # 绘制轮廓（如果存在）
        if detected and contour is not None:
            cv2.drawContours(debug_img, [contour], -1, (0, 0, 255), 2)
        
        # 创建调试图像：原始图像、掩码和边缘
        mask_rgb = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
        edges_rgb = cv2.cvtColor(edges, cv2.COLOR_GRAY2BGR)
        combined = np.hstack((debug_img, mask_rgb, edges_rgb))
        
        # 保存可视化结果
        output_path = f"debug_output_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
        cv2.imwrite(output_path, combined)
        print(f"可视化结果已保存至: {output_path}")

# 测试函数
def test_card_edge_detector():
    """测试卡片边缘检测模块"""
    detector = CardEdgeDetector()
    
    # 打开摄像头
    cap = VideoCapture()
    
    try:
        while True:
            img = cap.read()
            if img is None:
                print("无法读取图像")
                break
            
            # 调整图像大小
            img = cv2.resize(img, (640, 640))
            
            # 检测卡片边缘
            success, result = detector.detect_card_edge(img)
            
            # 打印结果
            print(f"检测结果: {result}")
            
            # 显示实时图像
            cv2.imshow('Card Edge Detection', img)
            if cv2.waitKey(1) & 0xFF == ord('q'):  # 按 'q' 退出
                break
            
            # 检测间隔
            time.sleep(0.5)
            
    except Exception as e:
        print(f"测试过程中发生错误: {str(e)}")
    finally:
        cap.release()
        cv2.destroyAllWindows()

if __name__ == "__main__":
    test_card_edge_detector()